package com.googlecode.skald.client.affordances;

/**
 * Represents a possible action of the player (end-user).
 * This could be a system-level command, a player-character action in the
 * game world, or a direction to an NPC to perform some action.
 * <p>
 * An Affordance is presented to the user as a possible action.  
 * If selected by the user, the Affordance produces an associated 
 * imperative command.  This command should then be sent back to the 
 * game world to affect its state.
 * <p>
 * Affordances may also be weakly-afforded and have an order setting,
 * which hints at their presentation order.
 * 
 * @author Zach Tomaszewski
 * @since 05 Nov 2012
 */
public interface Affordance extends Comparable<Affordance> {
  
  /** 
   * Specifies the increment at which to form a new group.
   * For example, if set to 100, any affordances with an order
   * between 0 and 99 will be in one group, 100 to 199 in another
   * group, and so on.  Groups are often visually separated, such
   * as with a divider or separator in menus, etc.
   * <p>
   * Current value is 100.
   */
  public int ORDER_GROUP_SIZE = 100;

  /**
   * Returns a sequence of elements that conveys all components of this 
   * affordance.
   * <p>
   * The normal use of this sequence is to build a corresponding menu that
   * describes the affordance, though a series of buttons or similar structure
   * could be constructed instead. Generally, the first element should be 
   * the verb or basic command, then each successive element corresponds to 
   * an additional argument.
   * <p>
   * These different elements may then be collapsed into a single element, 
   * either within the same affordance or across affordances.  For example,
   * elements ["Throw", "ball"] might be combined into "Throw ball", or 
   * the "ball" part may be dropped altogether if the menu was produced by 
   * clicking on the ball object.  Similarly, ["Throw", "ball"] and 
   * ["Throw", "stick"] might be collapsed into a single Throw menu with 
   * two elements in the corresponding submenu: "ball" and "stick".
   * <p>  
   * The specific details of this collapsing behavior usually depends 
   * on the user-interface context and the particular Affordance subtype. 
   */
  public String[] getDisplayElements();

  /**
   * Returns the text that should be sent to the server in order to execute
   * this affordance.
   */
  public String getCommandText();

  /**
   * Returns whether this affordance is only weakly afforded.
   * Weakly afforded affordances are actions that are possible-but-unusual 
   * or attemptable but likely to fail or actions that will be possible 
   * later after some precondition is met.  
   * <p>
   * Often, weakly afforded actions are presented for game world completeness 
   * (ie, this is something users might expect to be able to do), but 
   * selecting them just results in an response explaining why the action 
   * cannot be successful at this time.
   * <p>
   * However, weakness is ultimately just a style hint, so game authors may 
   * use it for different purposes. 
   */
  public boolean isWeak();
  
  /**
   * Returns the order of this affordance.  This controls the sort order, 
   * with smaller values coming before larger values.  It to also determines
   * which group the affordance falls into.
   * 
   * @see Affordance#ORDER_GROUP_SIZE
   */
  public int getOrder();

  /**
   * Affordances are sorted according to their order, then their 
   * display elements, and finally their commands.  Weakness is not considered.
   * <p>
   * Those affordances with a smaller (closer to negative infinity) order
   * come first.  Those with equal orders are then sorted by display elements.
   * Their top-level (first) elements are compared using normal 
   * case-sensitive String ordering.  If the top-level elements are 
   * equal, then the next element is compared, and so on.  Any non-element
   * comes before an existing element (ie, shorter arrays before longer).
   * <p>
   * If all display elements match, affordances are compared according to 
   * their command text.  This means Affordance comparison should be consistent 
   * with equals.
   */
  @Override
  public int compareTo(Affordance a);
  // FUTURE: If other Affordance subclasses appear, move this implementation
  // from PcAction into an AbstractAffordance class,
  // along with equals and hashCode
}
